package com.xunk.system.filter;

import com.xunk.common.core.utils.serialization.JsonSerializer;
import com.xunk.system.wrapper.HttpRequestWrapper;
import com.xunk.system.wrapper.HttpResponseWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: HIM
 * @Package: com.xunk.equipment.filter
 * @ClassName: LogFilter
 * @Author: luanzhiwei
 * @Description: 日志打印过滤，记录由外部服务发起，进入此服务的日志
 * @Date: 2021/4/26 19:20
 * @Version: 1.0
 */
@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE - 5)
public class LogFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (request.getRequestURI().contains("upload")) {
            filterChain.doFilter(request, response);
            return;
        }
        HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request);
        HttpResponseWrapper responseWrapper = new HttpResponseWrapper(response);
        // 请求地址
        String uri = requestWrapper.getRequestURI();
        //方法
        String method = requestWrapper.getMethod();
        // 请求headers
        String requestHeaders = getRequestHeaders(requestWrapper);
        // get请求的参数
        String requestParam = JsonSerializer.serialize(requestWrapper.getParameterMap());
        // post请求Body
        String bodyString = getBodyString(requestWrapper);
        // 打印请求信息
        log.info("Request-api, path：{},method: {}, headers {},requestParam: {},requestBody : {}", uri, method, requestHeaders, requestParam, bodyString);
        // 请求开始时间
        long begin = System.currentTimeMillis();
        // 重要：执行 SpringMVC 中 HandlerInterceptor 和 Controller
        filterChain.doFilter(requestWrapper, responseWrapper);
        //返回头
        String responseHeaders = getResponseHeaders(responseWrapper);
        //返回状态码
        int status = responseWrapper.getStatus();
        // 返回的结果
        String content = responseWrapper.getTextContent();
        //请求耗时
        long took = System.currentTimeMillis() - begin;
        // 打印返回结果 和 请求耗时
        log.info("Response-api, path: {},status: {}, headers: {},Response: {},took {} ms", uri, status, responseHeaders, content, took);
        response.getOutputStream().write(content.getBytes());

    }


    /**
     * 获取 HttpServletRequest 中 Body 参数
     *
     * @param request
     * @return
     */
    private String getBodyString(HttpServletRequest request) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    /**
     * 获取请求头
     *
     * @param request
     * @return
     */
    private String getRequestHeaders(HttpServletRequest request) {
        Map<String, String> headerMap = new HashMap<>();
        for (Enumeration<String> enumeration = request.getHeaderNames(); enumeration.hasMoreElements(); ) {
            String name = enumeration.nextElement();
            headerMap.put(name, request.getHeader(name));
        }
        return JsonSerializer.serialize(headerMap);
    }

    /**
     * 获取返回头
     *
     * @param response
     * @return
     */
    private String getResponseHeaders(HttpServletResponse response) {
        Map<String, String> headerMap = new HashMap<>();
        Collection<String> headerNames = response.getHeaderNames();
        for (String name : headerNames) {
            headerMap.put(name, response.getHeader(name));
        }
        return JsonSerializer.serialize(headerMap);
    }

}
